/*
 *  Copyright 2003 by Spectrum Digital Incorporated.
 *  All rights reserved. Property of Spectrum Digital Incorporated.
 */

/*
 *  ======== test.c ========
 *
 *  This test program performs a confidence test on severl of the DM642 EVM
 *  board components.  The following tests are performed:
 *
 *  Index   Description
 *    1     LEDs
 *    2     SPDIF/APLL/VCXO
 *    3     Synchronous Bus
 *    4     SDRAM
 *
 *    5     Flash (entire contents)
 *    6     I2C EEPROM
 *    7     UARTA Loopback
 *    8     UARTB Loopback
 *    9     PCI EEPROM
 */

/*
 *  DSP/BIOS is configured using the DSP/BIOS configuration tool.  Settings
 *  for this example are stored in a configuration file called test.cdb.  At
 *  compile time, Code Composer will auto-generate DSP/BIOS related files
 *  based on these settings.  A header file called testcfg.h contains the
 *  results of the autogeneration and must be included for proper operation.
 *  The name of the file is taken from test.cdb and adding cfg.h.
 */
#include "testcfg.h"

/*
 *  The POST uses the Chip Support Library for basic definitions as well as
 *  McBSP manipulation.  Programs that use the CSL must include the
 *  appropriate header files.
 */
#include <stdio.h>
#include <std.h>
#include <sys.h>
#include <csl.h>
#include <csl_mcbsp.h>
#include <csl_timer.h>
#include <csl_edma.h>
#include <csl_vic.h>
#include <csl_mcasp.h>
#include <csl_gpio.h>
#include <csl_pci.h>

/*
 *  The DM642 EVM Board Support Library is divided into several modules, each
 *  of which has its own include file.  The file evmdm642.h must be included
 *  in every program that uses the BSL.  This example also includes
 *  evmdm642_aic23.h, evmdm642_led.h and evmdm642_flash.h because it uses
 *  their respective BSL modules.
 */
#include "evmdm642.h"
#include "evmdm642_led.h"
#include "evmdm642_aic23.h"
#include "evmdm642_flash.h"
#include "evmdm642_eeprom.h"
#include "evmdm642_uart.h"
#include "evmdm642_apll.h"
#include "evmdm642_pci.h"

/* Length of sine wave table */
#define SINE_TABLE_SIZE  48

/* Number of elements for DMA and McBSP loopback tests */
#define N                16

/* Pre-generated sine wave data, 16-bit signed samples */
int sinetable[SINE_TABLE_SIZE] = {
    0x0000, 0x10b4, 0x2120, 0x30fb, 0x3fff, 0x4dea, 0x5a81, 0x658b,
    0x6ed8, 0x763f, 0x7ba1, 0x7ee5, 0x7ffd, 0x7ee5, 0x7ba1, 0x76ef,
    0x6ed8, 0x658b, 0x5a81, 0x4dea, 0x3fff, 0x30fb, 0x2120, 0x10b4,
    0x0000, 0xef4c, 0xdee0, 0xcf06, 0xc002, 0xb216, 0xa57f, 0x9a75,
    0x9128, 0x89c1, 0x845f, 0x811b, 0x8002, 0x811b, 0x845f, 0x89c1,
    0x9128, 0x9a76, 0xa57f, 0xb216, 0xc002, 0xcf06, 0xdee0, 0xef4c
};

/* Codec configuration settings */
EVMDM642_AIC23_Config config = {
    0x0017, // 0 EVMDM642_AIC23_LEFTINVOL  Left line input channel volume
    0x0017, // 1 EVMDM642_AIC23_RIGHTINVOL Right line input channel volume
    0x00d8, // 2 EVMDM642_AIC23_LEFTHPVOL  Left channel headphone volume
    0x00d8, // 3 EVMDM642_AIC23_RIGHTHPVOL Right channel headphone volume
    0x0011, // 4 EVMDM642_AIC23_ANAPATH    Analog audio path control
    0x0000, // 5 EVMDM642_AIC23_DIGPATH    Digital audio path control
    0x0000, // 6 EVMDM642_AIC23_POWERDOWN  Power down control
    0x0043, // 7 EVMDM642_AIC23_DIGIF      Digital audio interface format
    0x0081, // 8 EVMDM642_AIC23_SAMPLERATE Sample rate control
    0x0001  // 9 EVMDM642_AIC23_DIGACT     Digital interface activation
};

/* Define source and destination arrays for DMA and loopback tests */
Uint16 src[N], dst[N], buffer[256];

/* Variables used by the TEST_sleep() funciton */
Uint16 eventId1;
volatile Uint32 sleepCount = 0;

/* Flag to make sure POST only runs once after power cycle */
Uint32 testflag;

/* McASP definitions for SPDIF mode */
MCASP_ConfigGbl mcaspCfgDataGblSpdif = {
    0x00000000, /* PFUNC -     All pins as McASP */
    0x00000005, /* PDIR  -     XMT DATA output, rest are inputs */
    0x00000001, /* DITCTL -    DIT mode enable */
    0x00000000, /* DLBCTL -    Loopback disabled */
    0x00000000  /* AMUTE  -    Never drive AMUTE */
};

MCASP_ConfigRcv mcaspCfgDataRcvSpdif = {
    0x00000000, /* RMASK -     Inactive */
    0x00000000, /* RFMT -      Inactive */
    0x00000000, /* AFSRCTL -   Inactive */
    0x00000000, /* ACLKRCTL -  Inactive */
    0x00000000, /* AHCLKRCTL - Inactive */
    0x00000000, /* RTDM -      Inactive */
    0x00000000, /* RINTCTL -   Inactive */
    0x00000000  /* RCLKCHK -   Inactive */
};

MCASP_ConfigXmt mcaspCfgDataXmtSpdif = {
    0x00ffffff, /* XMASK -     Use 16 bits */
    0x000000f8, /* XFMT -      LSB first, 32-bit slots, CPU bus, 0 bit delay */
    0x0000c002, /* AFSXCTL -   384 slot DIT, int FS */
    0x00000061, /* ACLKXCTL -  Internal CLK, ASYNC, div by 2 */
    0x00000000, /* AHCLKXCTL - External HCLK, rising edge, div by 1 */
    0xffffffff, /* XTDM -      Enable all for DIT mode */
    0x00000000, /* XINTCTL -   No interrupts */
    0x00000000  /* XCLKCHK -   Not used */
};

MCASP_ConfigSrctl mcaspCfgDataSrctlSpdif = {
    0x00000000, /* SRCTL0 -    Inactive */
    0x00000000, /* SRCTL1 -    Inactive */
    0x0000000d, /* SRCTL2 -    Active */
    0x00000000, /* SRCTL3 -    Inactive */
    0x00000000, /* SRCTL4 -    Inactive */
    0x00000000, /* SRCTL5 -    Inactive */
    0x00000000, /* SRCTL6 -    Inactive */
    0x00000000  /* SRCTL7 -    Inactive */
};

MCASP_Config mcaspCfgDataSpdif = {
    &mcaspCfgDataGblSpdif,
    &mcaspCfgDataRcvSpdif,
    &mcaspCfgDataXmtSpdif,
    &mcaspCfgDataSrctlSpdif
};


/*
 *  Interrupt Service Routines
 */

void sleepIsr()
{
    sleepCount++;
}

/*
 *  Accessory functions
 */

void TEST_sleep(Int16 sleeptime)
{
    TIMER_Handle hTimer1;
    TIMER_Config timerCfg1 = {
        TIMER_FMKS(CTL, INVINP, NO)             |
        TIMER_FMKS(CTL, CLKSRC, CPUOVR8)        |
        TIMER_FMKS(CTL, CP, PULSE)              |
        TIMER_FMKS(CTL, HLD, YES)               |
        TIMER_FMKS(CTL, GO, NO)                 |
        TIMER_FMKS(CTL, PWID, ONE)              |
        TIMER_FMKS(CTL, DATOUT, 0)              |
        TIMER_FMKS(CTL, INVOUT, NO)             |
        TIMER_FMKS(CTL, FUNC, TOUT),

        TIMER_FMKS(PRD, PRD, OF(90000)),
        TIMER_FMKS(CNT, CNT, OF(0))
    };

    /* Open the timer */
    hTimer1 = TIMER_open(TIMER_DEV1, TIMER_OPEN_RESET);

    /* Configure the timer in one-shot mode */
    TIMER_config(hTimer1, &timerCfg1);

    /* Get Event Id associated with Timer 1, for use with */
    /* CSL interrupt enable functions.                    */
    eventId1 = TIMER_getEventId(hTimer1);

    /* Map the logical event to a physical interrupt */
    IRQ_map(eventId1, 15);

    /* Clear any pending Timer interrupts */
    IRQ_clear(eventId1);

    /* Enable timer interrupt */
    IRQ_enable(eventId1);

  	/* Make sure global interrupts are enabled */
  	IRQ_globalEnable();

    /* Clear sleep count */
    sleepCount = 0;

    /* Start timer 1 */
    TIMER_start(hTimer1);

    while(sleepCount < sleeptime);

    /* Disable timer interrupt */
    IRQ_disable(eventId1);

    TIMER_close(hTimer1);
}

void LED_binary(Int16 ledmask)
{
    Int16 i, bit;

    /* Walk through the bits in num setting corresponding LEDs */
    bit = 1;
    for (i = 0; i < 8; i++)
    {
        if (ledmask & bit)
            EVMDM642_LED_on(i);
        else
            EVMDM642_LED_off(i);
        bit = bit << 1;
    }
}

void LED_blink(Int16 ledmask, Int16 count)
{
    while (count > 0)
    {
        LED_binary(ledmask);
        TEST_sleep(100);
        LED_binary(0);
        TEST_sleep(150);
        count--;
    }
}

void LED_error(Int16 ledmask)
{
    while(1)
        LED_blink(ledmask, 1);
}

/*
 *  Memory functions
 */

Int16 MEM_fill(Uint32 start, Uint32 len, Uint32 val)
{
    Uint32 i, end;

    /* Calculate end of range */
    end = start + len;

    /* Fill a range with a value */
    for (i = start; i < end; i+=4)
    {
        *((Uint32 *)i) = val;
    }

    /* Verify the data */
    for (i = start; i < end; i+=4)
    {
        if (*((Uint32 *)i) != val)
            return 1;
    }

    return 0;
}

Int16 MEM_addr(Uint32 start, Uint32 len)
{
    Uint32 i, end;

    /* Calculate end of range */
    end = start + len;

    /* Fill the range with its address */
    for (i = start; i < end; i+=4)
    {
        *((Uint32 *)i) = i;
    }

    /* Verify the data */
    for (i = start; i < end; i+=4)
        if (*((Uint32 *)i) != i)
            return 2;

    return 0;
}

Int16 MEM_addrInv(Uint32 start, Uint32 len)
{
    Uint32 i, end;

    /* Calculate end of range */
    end = start + len;

    /* Fill the range with its address */
    for (i = start; i < end; i+=4)
    {
        *((Uint32 *)i) = ~i;
    }

    /* Verify the data */
    for (i = start; i < end; i+=4)
        if (*((Uint32 *)i) != (~i))
            return 4;

    return 0;
}

Int16 MEM_walking(Uint32 add)
{
    Int16 i;
    Uint32 mask, *pdata;

    pdata = (Uint32 *)add;

    /* Walking ones and zeros */
    mask = 1;
    for (i = 0; i < 32; i++)
    {
        /* Test one in bit position i */
        *pdata = mask;

        /* Do a dummy write to Flash to clear bus */
        *((Uint8 *)EVMDM642_FLASH_BASE) = 0xf0;

        /* Check data */
        if (*pdata != mask)
            return 1;

        /* Test zero in bit position i */
        *pdata = ~mask;

        /* Do a dummy write to Flash to clear bus */
        *((Uint8 *)EVMDM642_FLASH_BASE) = 0xf0;

        /* Check data */
        if (*pdata != (~mask))
            return 8;

        mask = mask << 1;
    }

    return 0;
}

Int16 MEM_bytestrobe(Uint32 add)
{
    Uint32 *pdata;
    Uint8 *pcheck;

    /* Write pattern */
    pdata = (Uint32 *)add;
    *pdata = 0x12345678;

    /* Do dummy write */
    pdata = (Uint32 *)EVMDM642_FLASH_BASE;
    *pdata = 0x80808080;

    /* Check pattern */
    pcheck = (Uint8 *)add;
    if (*pcheck++ != 0x78)
        return 0x10;
    if (*pcheck++ != 0x56)
        return 0x20;
    if (*pcheck++ != 0x34)
        return 0x40;
    if (*pcheck++ != 0x12)
        return 0x80;

    return 0;
}

Int16 MEM_test(Uint32 start, Uint32 len, Int16 patterntype)
{
    Int16 status = 0;

    if (!patterntype)
    {
        /* Run the fill tests */
        status |= MEM_fill(start, len, 0x00000000);
        status |= MEM_fill(start, len, 0x55555555);
        status |= MEM_fill(start, len, 0xAAAAAAAA);
        status |= MEM_fill(start, len, 0xFFFFFFFF);
    } else
    {
        /* Run the address tests */
        status |= MEM_addr(start, len);
        status |= MEM_addrInv(start, len);
    }

    return status;
}


/*
 *  POST tests
 */

Int16 TEST_intMem()
{
    Int16 status = 0;

    /* Check internal memory (byte 0x20000 to byte 0x40000) */
    status |= MEM_test(0x20000, 0x20000, 0);
    status |= MEM_test(0x20000, 0x20000, 1);
    status |= MEM_walking(0x20000);

    return status;
}

Int16 TEST_extMem()
{
    Int16 status = 0;

    /* Check external memory (byte 0x80000000 to byte 0x82000000) */
    status |= MEM_test(0x80000000, 0x02000000, 0);
    status |= MEM_test(0x80000000, 0x02000000, 1);
    status |= MEM_walking(0x80000000);
    status |= MEM_bytestrobe(0x80000000);

    return status;
}

Int16 TEST_mcbsp(int devid, Int16 delayed)
{
    Int16 i;
    Uint16 receivedata;
    MCBSP_Handle hMcbsp;
    MCBSP_Config mcbspCfg_loopback = {
        MCBSP_FMKS(SPCR, FREE, NO)              |
        MCBSP_FMKS(SPCR, SOFT, NO)              |
        MCBSP_FMKS(SPCR, FRST, YES)             |
        MCBSP_FMKS(SPCR, GRST, YES)             |
        MCBSP_FMKS(SPCR, XINTM, XRDY)           |
        MCBSP_FMKS(SPCR, XSYNCERR, NO)          |
        MCBSP_FMKS(SPCR, XRST, YES)             |
        MCBSP_FMKS(SPCR, DLB, ON)               |
        MCBSP_FMKS(SPCR, RJUST, RZF)            |
        MCBSP_FMKS(SPCR, CLKSTP, DISABLE)       |
        MCBSP_FMKS(SPCR, DXENA, OFF)            |
        MCBSP_FMKS(SPCR, RINTM, RRDY)           |
        MCBSP_FMKS(SPCR, RSYNCERR, NO)          |
        MCBSP_FMKS(SPCR, RRST, YES),

        MCBSP_FMKS(RCR, RPHASE, SINGLE)         |
        MCBSP_FMKS(RCR, RFRLEN2, DEFAULT)       |
        MCBSP_FMKS(RCR, RWDLEN2, DEFAULT)       |
        MCBSP_FMKS(RCR, RCOMPAND, MSB)          |
        MCBSP_FMKS(RCR, RFIG, NO)               |
        MCBSP_FMKS(RCR, RDATDLY, 0BIT)          |
        MCBSP_FMKS(RCR, RFRLEN1, OF(0))         |
        MCBSP_FMKS(RCR, RWDLEN1, 16BIT)         |
        MCBSP_FMKS(RCR, RWDREVRS, DISABLE),

        MCBSP_FMKS(XCR, XPHASE, SINGLE)         |
        MCBSP_FMKS(XCR, XFRLEN2, DEFAULT)       |
        MCBSP_FMKS(XCR, XWDLEN2, DEFAULT)       |
        MCBSP_FMKS(XCR, XCOMPAND, MSB)          |
        MCBSP_FMKS(XCR, XFIG, NO)               |
        MCBSP_FMKS(XCR, XDATDLY, 0BIT)          |
        MCBSP_FMKS(XCR, XFRLEN1, OF(0))         |
        MCBSP_FMKS(XCR, XWDLEN1, 16BIT)         |
        MCBSP_FMKS(XCR, XWDREVRS, DISABLE),

        MCBSP_SRGR_DEFAULT,
        MCBSP_MCR_DEFAULT,
        MCBSP_RCERE0_DEFAULT,
        MCBSP_RCERE1_DEFAULT,
        MCBSP_RCERE2_DEFAULT,
        MCBSP_RCERE3_DEFAULT,
        MCBSP_XCERE0_DEFAULT,
        MCBSP_XCERE1_DEFAULT,
        MCBSP_XCERE2_DEFAULT,
        MCBSP_XCERE3_DEFAULT,

        MCBSP_FMKS(PCR, XIOEN, DEFAULT)         |
        MCBSP_FMKS(PCR, RIOEN, DEFAULT)         |
        MCBSP_FMKS(PCR, FSXM, INTERNAL)         |
        MCBSP_FMKS(PCR, FSRM, DEFAULT)          |
        MCBSP_FMKS(PCR, CLKXM, OUTPUT)          |
        MCBSP_FMKS(PCR, CLKRM, INPUT)           |
        MCBSP_FMKS(PCR, CLKSSTAT, DEFAULT)      |
        MCBSP_FMKS(PCR, DXSTAT, DEFAULT)        |
        MCBSP_FMKS(PCR, FSXP, DEFAULT)          |
        MCBSP_FMKS(PCR, FSRP, DEFAULT)          |
        MCBSP_FMKS(PCR, CLKXP, DEFAULT)         |
        MCBSP_FMKS(PCR, CLKRP, DEFAULT)
    };

    /* Initialize source data, zero dest */
    for (i = 0; i < N; i++) {
        src[i] = (i << 8) | i + 1;
        dst[i] = 0;
    }

    /* Open the McBSP */
    hMcbsp = MCBSP_open(devid, MCBSP_OPEN_RESET);

    /* Configure the McBSP for loopback mode */
    MCBSP_config(hMcbsp, &mcbspCfg_loopback);

    /* Start the McBSP */
    MCBSP_start(hMcbsp, MCBSP_RCV_START | MCBSP_XMIT_START |
        MCBSP_SRGR_START | MCBSP_SRGR_FRAMESYNC, MCBSP_SRGR_DEFAULT_DELAY);

    /* Data transfer loop */
    for (i = 0; i < (N + delayed); i++) {
        /* Wait for XRDY signal before writing data to DXR */
        while (!MCBSP_xrdy(hMcbsp));

        /* Write 16 bit data value to DXR */
        MCBSP_write(hMcbsp,src[i]);

        /* Wait for RRDY signal to read data from DRR */
        while (!MCBSP_rrdy(hMcbsp));

        /* Read 16 bit value from DRR */
        receivedata = MCBSP_read(hMcbsp);
        if (i >= delayed)
            dst[i - delayed] = receivedata;
    }

    /* Close the McBSP */
    MCBSP_close(hMcbsp);

    /* Check data to make sure transfer was successful */
    for (i = 0; i < N; i++)
        if (dst[i] != src[i])
            return 1;

    /* Test passed */
    return 0;
}

Int16 TEST_mcbsp0()
{
    /* Do an internal loopback test on McBSP0 */
    return TEST_mcbsp(MCBSP_DEV0, 0);
}

Int16 TEST_mcbsp1()
{
    /* Do an internal loopback test on McBSP1 */
    return TEST_mcbsp(MCBSP_DEV1, 0);
}

Int16 TEST_dma()
{
    Int16 i;
    EDMA_Handle hEdmaCha8;
    EDMA_Config edmaCfg8 = {
        EDMA_FMKS(OPT, PRI, URGENT)           |
        EDMA_FMKS(OPT, ESIZE, 16BIT)          |
        EDMA_FMKS(OPT, 2DS, NO)               |
        EDMA_FMKS(OPT, SUM, INC)              |
        EDMA_FMKS(OPT, 2DD, NO)               |
        EDMA_FMKS(OPT, DUM, INC)              |
        EDMA_FMKS(OPT, TCINT, YES)            |
        EDMA_FMK (OPT, TCC, 8)                |
        EDMA_FMKS(OPT, TCCM, DEFAULT)         |
        EDMA_FMKS(OPT, ATCINT, NO)            |
        EDMA_FMKS(OPT, ATCC, DEFAULT)         |
        EDMA_FMKS(OPT, PDTS, DEFAULT)         |
        EDMA_FMKS(OPT, PDTD, DEFAULT)         |
        EDMA_FMKS(OPT, LINK, NO)              |
        EDMA_FMKS(OPT, FS, YES),

        (Uint32)src,

        EDMA_FMKS(CNT, FRMCNT, OF(0))         |
        EDMA_FMKS(CNT, ELECNT, OF(16)),

        (Uint32)dst,

        EDMA_FMKS(IDX, FRMIDX, DEFAULT)       |
        EDMA_FMKS(IDX, ELEIDX, DEFAULT),

        EDMA_FMKS(RLD, ELERLD, DEFAULT)       |
        EDMA_FMKS(RLD, LINK, DEFAULT)
    };

    /* Set src values and clear destination */
    for (i = 0; i < N; i++) {
        src[i] = i;
        dst[i] = 0;
    }

    /* Configure EDMA */
    hEdmaCha8 = EDMA_open(8, EDMA_OPEN_RESET);
    EDMA_config(hEdmaCha8, &edmaCfg8);

    /* Start CPU initiated EDMA transfer by setting bit 24 in ESR */
    EDMA_setChannel(hEdmaCha8);

    /* Poll DMA interrupt too see if its done */
    while (!EDMA_intTest(8));
    {
    	;
    }

    /* We are done, so close DMA channel */
    EDMA_close(hEdmaCha8);

    /* Check data */
    for (i = 0; i < N; i++)
        if (dst[i] != src[i])
            return 1;

    /* Test passed */
    return 0;
}

Int16 TEST_timer()
{
    /* Wait for 100 timer interrupts */
    TEST_sleep(100);

    return 0;
}


/*
 *  Diagnostic utility specific tests
 */

Int16 TEST_flashall()
{
    Uint16 i, j, k, page, limit;
    Uint32 startaddr, addr;

    /* Program the Flash page by page, 256 words at a time */
    for (page = 0; page < 8; page++)
    {
        /* Set Flash page */
        EVMDM642_rset(EVMDM642_FLASHPAGE, page);

        /* Turn activity indicator off */
        EVMDM642_LED_off(7);

        /* Erase all of the Flash */
        EVMDM642_FLASH_erase(EVMDM642_FLASH_BASE, EVMDM642_FLASH_PAGESIZE);

        /* Turn activity indicator on */
        EVMDM642_LED_on(7);

        addr = EVMDM642_FLASH_BASE;
        if (page == 0)
            limit = 8;
        else
            limit = 1;
        for (i = 0; i < limit; i++)
        {
            for (j = 0; j < 128; j++)
            {
                startaddr = addr;
                for (k = 0; k < 256; k++)
                {
                    buffer[k] = addr + i + page;
                    addr += 2;
                }
                EVMDM642_FLASH_write((Uint32)buffer, startaddr, 512);
            }
        }
    }

    /* Verify the Flash page by page, 256 bytes at a time */
    for (page = 0; page < 8; page++)
    {
        /* Set Flash page */
        EVMDM642_rset(EVMDM642_FLASHPAGE, page);

        addr = EVMDM642_FLASH_BASE;
        if (page == 0)
            limit = 8;
        else
            limit = 1;
        for (i = 0; i < limit; i++)
        {
            for (j = 0; j < 128; j++)
            {
                startaddr = addr;
                EVMDM642_FLASH_read(startaddr, (Uint32)buffer, 512);
                for (k = 0; k < 256; k++)
                {
                    if (buffer[k] != ((addr + i + page) & 0xffff))
                        return page + 1;
                    addr += 2;
                }
            }
        }
    }

    return 0;
}

Int16 TEST_syncbus()
{
    return MEM_walking(EVMDM642_SYNC_BASE);
}

Int16 TEST_led()
{
    Uint32 i, j;

    EVMDM642_LED_init();
    for (i = 0; i < 64; i++)
    {
        LED_binary(0xaa);
        for (j = 0; j < 1000000; j++);
        LED_binary(0x55);
        for (j = 0; j < 1000000; j++);
    }
    LED_binary(0xff);

    return 0;
}

Int16 TEST_spdif()
{
    Uint32 i, j, data, *pdata;

    /* Open and configure the McASP */
    EVMDM642_AIC23_hMcASP = MCASP_open(MCASP_DEV0, MCASP_OPEN_RESET);
    MCASP_config(EVMDM642_AIC23_hMcASP, &mcaspCfgDataSpdif);

    /* Configure DIT status and user registers */
    pdata = (Uint32 *)0x1b4c0;
    for (i = 0; i < 24; i++)
        *pdata++ = 0xffffffff;

    /* Enable transmit clocks and serializers */
    MCASP_RSETH(EVMDM642_AIC23_hMcASP, GBLCTL, 0x00000200);
    while (MCASP_RGETH(EVMDM642_AIC23_hMcASP, GBLCTL) != 0x00000200);

    /* Enable transmit clocks and serializers */
    MCASP_RSETH(EVMDM642_AIC23_hMcASP, GBLCTL, 0x00000300);
    while (MCASP_RGETH(EVMDM642_AIC23_hMcASP, GBLCTL) != 0x00000300);
    for (i = 0; i < 1000; i++);

    /* Enable transmit and receive clocks and serializers */
    MCASP_RSETH(EVMDM642_AIC23_hMcASP, GBLCTL, 0x00000700);
    while (MCASP_RGETH(EVMDM642_AIC23_hMcASP, GBLCTL) != 0x00000700);

    /* Put some data in the transmit buffer */
    MCASP_RSETH(EVMDM642_AIC23_hMcASP, XBUF2, 0);

    /* Release transmit and receive state machines */
    MCASP_RSETH(EVMDM642_AIC23_hMcASP, GBLCTL, 0x00000f00);
    while (MCASP_RGETH(EVMDM642_AIC23_hMcASP, GBLCTL) != 0x00000f00);

    /* Release transmit and receive state machines */
    MCASP_RSETH(EVMDM642_AIC23_hMcASP, GBLCTL, 0x00001f00);

    /* Generate 1KHz sine wave for 5 seconds*/
    for (i = 0; i < 5000; i++)
    {
        for (j = 0; j < SINE_TABLE_SIZE; j++)
        {
            data = sinetable[j];

            /* Wait until serializer ready to transmit */
            while ((MCASP_RGETH(EVMDM642_AIC23_hMcASP, SRCTL2) & 0x10) == 0);

            /* Transmit data */
            MCASP_RSETH(EVMDM642_AIC23_hMcASP, XBUF2, data);

            /* Wait until serializer ready to transmit */
            while ((MCASP_RGETH(EVMDM642_AIC23_hMcASP, SRCTL2) & 0x10) == 0);

            /* Transmit data */
            MCASP_RSETH(EVMDM642_AIC23_hMcASP, XBUF2, data);
        }
    }

    MCASP_close(EVMDM642_AIC23_hMcASP);

    return 0;
}

Int16 TEST_audioclks()
{
    Uint32 testtime;
    Int16 status;
    TIMER_Handle hTimer1;
    TIMER_Config timerCfg1 = {
        TIMER_FMKS(CTL, INVINP, NO)             |
        TIMER_FMKS(CTL, CLKSRC, CPUOVR8)        |
        TIMER_FMKS(CTL, CP, PULSE)              |
        TIMER_FMKS(CTL, HLD, YES)               |
        TIMER_FMKS(CTL, GO, NO)                 |
        TIMER_FMKS(CTL, PWID, ONE)              |
        TIMER_FMKS(CTL, DATOUT, 0)              |
        TIMER_FMKS(CTL, INVOUT, NO)             |
        TIMER_FMKS(CTL, FUNC, TOUT),

        TIMER_FMKS(PRD, PRD, OF(90)),
        TIMER_FMKS(CNT, CNT, OF(0))
    };

    status = 0;

    /* Enable GPIO on VDAC pin */
    GPIO_pinEnable(EVMDM642_GPIO_hGPIO, GPIO_PIN8);

    /* Configure as output */
    GPIO_pinDirection(EVMDM642_GPIO_hGPIO, GPIO_PIN8, GPIO_OUTPUT);

    /* Open the timer */
    hTimer1 = TIMER_open(TIMER_DEV1, TIMER_OPEN_RESET);

    /* Configure the timer in one-shot mode */
    TIMER_config(hTimer1, &timerCfg1);

    /* Get Event Id associated with Timer 1, for use with */
    /* CSL interrupt enable functions.                    */
    eventId1 = TIMER_getEventId(hTimer1);

    /* Map the logical event to a physical interrupt */
    IRQ_map(eventId1, 15);

    /* Clear any pending Timer interrupts */
    IRQ_clear(eventId1);

    /* Enable timer interrupt */
    IRQ_enable(eventId1);

  	/* Make sure global interrupts are enabled */
  	IRQ_globalEnable();

    /* Start timer 1 */
    TIMER_start(hTimer1);

    /* Set audio PLL to 18.432 MHz, VDAC low */
    EVMDM642_APLL_rset(EVMDM642_APLL_FSG0);
    GPIO_pinWrite(EVMDM642_GPIO_hGPIO, GPIO_PIN8, 0);
    sleepCount = 0;

    /* Check test duration against timer */
    TEST_spdif();

    testtime = sleepCount;
    printf("       Timer1 count -> %d\n", testtime);

    if (testtime > 4999900)
    {
        status = 1;
        goto SPDIF_END;
    }

    /* Drive VDAC high */
    GPIO_pinWrite(EVMDM642_GPIO_hGPIO, GPIO_PIN8, 1);
    sleepCount = 0;

    /* Check test duration against timer */
    TEST_spdif();

    testtime = sleepCount;
    printf("       Timer2 count -> %d\n", testtime);

    if (testtime < 5000280)
    {
        status = 2;
        goto SPDIF_END;
    }

    /* Set audio PLL to 16.9344 MHz */
    EVMDM642_APLL_rset(EVMDM642_APLL_FSG1);
    GPIO_pinWrite(EVMDM642_GPIO_hGPIO, GPIO_PIN8, 0);
    sleepCount = 0;

    /* Check test duration against timer */
    TEST_spdif();

    testtime = sleepCount;
    printf("       Timer3 count -> %d\n", testtime);

    if (testtime > 5442070)
    {
        status = 3;
        goto SPDIF_END;
    }

    /* Drive VDAC high */
    GPIO_pinWrite(EVMDM642_GPIO_hGPIO, GPIO_PIN8, 1);
    sleepCount = 0;

    /* Check test duration against timer */
    TEST_spdif();

    testtime = sleepCount;
    printf("       Timer4 count -> %d\n", testtime);

    if (testtime < 5442470)
    {
        status = 4;
        goto SPDIF_END;
    }

SPDIF_END:
    TIMER_close(hTimer1);

    return status;
}

Int16 TEST_eeprom()
{
    Uint16 page, i;
    Uint8 *pdata;

    /* Write a pattern */
    for (page = 0; page < 4; page++)
    {
        pdata = (Uint8 *)buffer;
        for (i = 0; i < 64; i++)
            *pdata++ = (page + i) & 0xff;
        EVMDM642_EEPROM_write((Uint32)buffer, page << 6, 64);
    }

    /* Verify the pattern */
    for (page = 0; page < 4; page++)
    {
        EVMDM642_EEPROM_read(page << 6, (Uint32)buffer, 64);
        pdata = (Uint8 *)buffer;
        for (i = 0; i < 64; i++)
            if (*pdata++ != (page + i) & 0xff)
                return 1;  // Fail
    }

    return 0;
}

Int16 TEST_uartA()
{
    Int16 i;
    EVMDM642_UART_Handle hUart;
    EVMDM642_UART_Config uartcfg = {
        0x00,  // IER
        0x57,  // FCR - FIFO Mode, 16 character trigger level
        0x03,  // LCR - 8 bits, no parity, 1 stop
        0x00   // MCR
    };

    /* Open UART */
    hUart = EVMDM642_UART_open(EVMDM642_UARTA, EVMDM642_UART_BAUD19200, &uartcfg);

    /* Loop through 256 bytes */
    for (i = 0; i < 256; i++)
    {
        EVMDM642_UART_putChar(hUart, (i + 1) & 0xff);
        buffer[i] = EVMDM642_UART_getChar(hUart);
    }

    /* Verify data */
    for (i = 0; i < 256; i++)
    {
        if (buffer[i] != ((i + 1) & 0xff))
            return 1;
    }

    return 0;
}

Int16 TEST_uartB()
{
    Int16 i;
    EVMDM642_UART_Handle hUart;
    EVMDM642_UART_Config uartcfg = {
        0x00,  // IER
        0x57,  // FCR - FIFO Mode, 16 character trigger level
        0x03,  // LCR - 8 bits, no parity, 1 stop
        0x00   // MCR
    };

    /* Open UART */
    hUart = EVMDM642_UART_open(EVMDM642_UARTB, EVMDM642_UART_BAUD19200, &uartcfg);

    /* Loop through 256 bytes */
    for (i = 0; i < 256; i++)
    {
        EVMDM642_UART_putChar(hUart, (i + 1) & 0xff);
        buffer[i] = EVMDM642_UART_getChar(hUart);
    }

    /* Verify data */
    for (i = 0; i < 256; i++)
    {
        if (buffer[i] != ((i + 1) & 0xff))
            return 1;
    }

    return 0;
}

Int16 TEST_pciregs()
{
    Uint16 i, n;

    Uint16 configregs[13] = {
        0x104c,  // 0
        0x9065,  // 1
        0x0000,  // 2
        0xff00,  // 3
        0x1652,  // 4
        0x0642,  // 5
        0x0000,  // 6
        0x0000,  // 7
        0x0000,  // 8
        0x0000,  // 9
        0x0000,  // 10
        0x0000,  // 11
        0x0000   // 12
    };

    EVMDM642_PCI_config(configregs);

    /* Read test values */
    for (i = 0; i < 13; i++)
    {
        n = PCI_eepromRead(i);
        if (n != configregs[i])
            return 1;
    }

    return 0;
}

void TEST_execute(Int16 (*funchandle)(), char *testname, Int16 ledmask, Int16 insertdelay)
{
    Int16 status;

    /* Display test ID */
    printf("%02d  Testing %s...\n", ledmask, testname);

    /* Call test function */
    status = funchandle();

    /* Check for test fail */
    if (status > 0)
    {
        /* Print error message */
        printf("     FAIL... error code %d... quitting\n", status, testname);

        /* Software breakpoint */
        asm(" .long 0x10000000");
    } else
    {
        /* Print error message */
        printf("    PASS\n", testname);
    }
}

main()
{
    /* Call BSL init */
    EVMDM642_init();

    /* Set initial LED state */
    EVMDM642_LED_init();

    /* Run the tests sequentially */
    TEST_execute(TEST_led,       "LEDs",            1, 0);
//  TEST_execute(TEST_audioclks, "SPDIF/APLL/VCXO", 2, 0);
//  TEST_execute(TEST_syncbus,   "Sync Bus",        3, 0);
    TEST_execute(TEST_extMem,    "SDRAM",           4, 0);
    TEST_execute(TEST_flashall,  "Flash",           5, 0);
//  TEST_execute(TEST_eeprom,    "I2C EEPROM",      6, 0);
//  TEST_execute(TEST_uartA,     "UARTA",           7, 0);
//  TEST_execute(TEST_uartB,     "UARTB",           8, 0);
//  TEST_execute(TEST_pciregs,   "PCI EEPROM",      9, 1);

    /* Success */
    printf("\n*** All tests PASS ***\n");

    /* Disable interrupts */
    IRQ_globalDisable();

    /* Software breakpoint */
    asm(" .long 0x10000000");
}
